﻿using Microsoft.Practices.Prism.Commands;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;
using System.Windows.Threading;

namespace HobSoft.SoccerBet2014.Client.ViewModels
{
    using Domain.ClientService;
    using Domain.Schedule;
    using Domain.Implementation;
    using Domain.Models.Site;
    using Common;

    public class BmAccount : CommandViewModel, IDisposable
    {
        public event EventHandler<BmAccount> OnDeleteRequest;

        #region command
        public ICommand SignupCommand { get; protected set; }
        public ICommand SignoutCommand { get; protected set; }
        public ICommand DeleteCommand { get; protected set; }
        #endregion

        public IBetSiteProxyService BetManagerProxy;
        public ITimer ScheduleTimer;

        public BmAccount()
        {
            SignupCommand = new DelegateCommand(Signup, CanSingup);
            SignoutCommand = new DelegateCommand(Signout, CanSignout);
            DeleteCommand = new DelegateCommand(Delete, CanDelete);
            RegisterCommand(SignupCommand, "登录");
            RegisterCommand(SignoutCommand, "注销");
            RegisterCommand(DeleteCommand, "删除");

            CountDownTimer = new DispatcherTimer();
            CountDownTimer.Interval = TimeSpan.FromSeconds(1);
            CountDownTimer.Tick += CountDownTimer_Tick;
            CountDownTimer.Start();
            OnValid = Valid();
        }

        #region local method
        public bool Valid()
        {
            return BmID > 0 && !string.IsNullOrEmpty(Account) && !string.IsNullOrEmpty(Password);
        }

        protected void ResetBookmakerState()
        {
            if (Bookmakers == null) return;
            var bm = Bookmakers.FirstOrDefault(b => b.BmID == BmID);
            if (bm == null) return;
            bm.AccountUse = OnSignup;
        }
        #endregion

        #region raise event&event handler
        protected void CountDownTimer_Tick(object sender, EventArgs e)
        {
            if (!OnSignup) return;
            if (LastLiveRequest.HasValue)
                LiveCountdown = (int)(DateTime.Now - LastLiveRequest.Value).TotalSeconds;

            if (LastTodayRequest.HasValue)
                TodayCountdown = (int)(DateTime.Now - LastTodayRequest.Value).TotalSeconds;

            if (LastEarlyRequest.HasValue)
                EarlyCountdown = (int)(DateTime.Now - LastEarlyRequest.Value).TotalSeconds;
        }

        #endregion

        public ReadOnlyObservableCollection<Bookmaker> Bookmakers
        {
            get;
            set;
        }

        #region command imple
        protected bool CanDelete()
        {
            return !OnSignup;
        }

        protected void Delete()
        {
            if (OnSignup) return;
            if (OnDeleteRequest != null)
                OnDeleteRequest(this, this);
        }

        protected bool CanSignout()
        {
            return OnInitialized && OnSignup&& !CommandOnExecuting(SignoutCommand);
        }

        public void Signout()
        {
            RaiseCommandStart(SignoutCommand, "开始注销账号");
            RaiseCommandCanExecute(SignupCommand);
            StopSchedule();
            BetManagerProxy.Sigout(BmID, Account).ContinueWith(t =>
            {
                BetApplication.Current.Dispatcher.Invoke(() =>
                {
                    OnSignup = false;
                    RaiseCommandOver(SignoutCommand, "完成注销账号");
                    if (t.Exception != null)
                    {
                        SiteState = "注销发生错误";
                    }
                    else
                    {
                        SiteState = "已注销";
                    }
                    PublicLog.InfoFormat("{0}注销成功", Account);
                    RaiseCommandCanExecute(SignoutCommand);
                    RaiseCommandCanExecute(SignupCommand);
                    RaiseCommandCanExecute(DeleteCommand);
                });
            });
        }

        protected bool CanSingup()
        {
            return OnInitialized && !OnSignup && !CommandOnExecuting(SignupCommand);
        }

        public void Signup()
        {
            if (Bookmakers == null)
            {
                OnSignup = false;
                SiteState = "账号没有指定网站";
                return;
            }
            var bm = Bookmakers.FirstOrDefault(b => b.BmID == BmID);
            if (bm == null)
            {
                OnSignup = false;
                SiteState = "账号没有指定网站";
                return;
            }

            RaiseCommandStart(SignupCommand, "开始登录网站");
            RaiseCommandCanExecute(SignupCommand);

            BetManagerProxy.Register(BmID, Account);
            BetManagerProxy.Signup(BmID, Account, Password).ContinueWith(t =>
            {
                BetApplication.Current.Dispatcher.Invoke(() =>
                {
                    RaiseCommandOver(SignupCommand, "完成登录网站");
                    if (t.Exception != null)
                    {
                        OnSignup = false;
                        SiteState = "登录发生错误";
                        PublicLog.ErrorFormat("{0}登录错误：{1}", Account, t.Exception.InnerException.Message);
                        RaiseCommandCanExecute(SignupCommand);
                        return;
                    }
                    if (!t.Result)
                    {
                        OnSignup = false;
                        SiteState = "登录失败";
                        PublicLog.WarnFormat("{0}登录失败", Account);
                        RaiseCommandCanExecute(SignupCommand);
                        return;
                    }
                    BetApplication.SubmitCacheModel<AccountCookie>();
                    BetApplication.SubmitCacheModel<SiteContext>();
                    PublicLog.InfoFormat("{0}登录成功", Account);
                    SiteState = "已经登录";
                    OnSignup = true;
                    RaiseCommandCanExecute(SignupCommand);
                    RaiseCommandCanExecute(SignoutCommand);
                    RaiseCommandCanExecute(DeleteCommand);
                    StartSchedule();
                });
            });
        }

        public void StartSchedule()
        {
            if (BetManagerProxy == null)
                return;
            BetManagerProxy.StartSchedule(BmID, Account);
            CountDownTimer.Start();
        }

        public void StopSchedule()
        {
            if (BetManagerProxy == null) return;
            BetManagerProxy.StopSchedule(BmID, Account);
            CountDownTimer.Stop();
        }

        public void ResetUpdateState(BetSiteRequestType type, DateTime lastUpdateTime)
        {
            switch (type)
            {
                case BetSiteRequestType.Live:
                    LastLiveRequest = lastUpdateTime;
                    break;
                case BetSiteRequestType.Today:
                    LastTodayRequest = lastUpdateTime;
                    break;
                case BetSiteRequestType.Early:
                    LastEarlyRequest = lastUpdateTime;
                    break;
                default:
                    break;
            }
        }
        #endregion

        #region model porperty
        private bool _onValid;
        public bool OnValid
        {
            get { return _onValid; }
            set
            {
                PropertyValueChange(ref _onValid, value, "OnValid");
            }
        }

        private bool _onSignup;
        public bool OnSignup
        {
            get { return _onSignup; }
            set
            {
                PropertyValueChange(ref _onSignup, value, "OnSignup");
                ResetBookmakerState();
            }
        }

        private string _siteState;
        public string SiteState
        {
            get { return _siteState; }
            set
            {
                PropertyValueChange(ref _siteState, value, "SiteState");
            }
        }

        private byte _bmId;
        public byte BmID
        {
            get { return _bmId; }
            set
            {
                if (OnSignup)
                    throw new Exception("请退出登录后修改博彩网站");
                PropertyValueChange(ref _bmId, value, "BmID");
                OnValid = Valid();
            }
        }

        private string _account;
        public string Account
        {
            get { return _account; }
            set
            {
                if (OnSignup)
                    throw new Exception("请退出登录后修改账号");
                PropertyValueChange(ref _account, value, "Account");
                OnValid = Valid();
            }
        }

        private string _password;
        public string Password
        {
            get { return _password; }
            set
            {
                if (OnSignup)
                    throw new Exception("请退出登录后修改密码");
                PropertyValueChange(ref _password, value, "Password");
                OnValid = Valid();
            }
        }

        private decimal? _discount;
        public decimal? Discount
        {
            get { return _discount; }
            set { PropertyValueChange(ref _discount, value, "Discount"); }
        }
        #endregion

        #region site request proxy property

        protected DispatcherTimer CountDownTimer;

        private int _liveCountdown;
        public int LiveCountdown
        {
            get
            {
                return _liveCountdown;
            }
            protected set
            {
                if (_liveCountdown == value) return;
                RaisePropertyChanging("LiveCountdown");
                _liveCountdown = value;
                RaisePropertyChanged("LiveCountdown");
            }
        }
        public DateTime? LastLiveRequest
        {
            get;
            protected set;
        }
        private int _todayCountdown;
        public int TodayCountdown
        {
            get
            {
                return _todayCountdown;
            }
            protected set
            {
                if (_todayCountdown == value) return;
                RaisePropertyChanging("TodayCountdown");
                _todayCountdown = value;
                RaisePropertyChanged("TodayCountdown");
            }
        }
        public DateTime? LastTodayRequest
        {
            get;
            protected set;
        }
        private int _earlyCountdown;
        public int EarlyCountdown
        {
            get
            {
                return _earlyCountdown;
            }
            protected set
            {
                if (_earlyCountdown == value) return;
                RaisePropertyChanging("EarlyCountdown");
                _earlyCountdown = value;
                RaisePropertyChanged("EarlyCountdown");
            }
        }
        public DateTime? LastEarlyRequest
        {
            get;
            protected set;
        }
        #endregion

        public void Dispose()
        {
            if (CountDownTimer != null)
                CountDownTimer.Stop();
        }
    }
}
